import javafx.util.Pair;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author hewei
 * @version 1.0
 * @description: 1139. 最大的以 1 为边界的正方形
 * @date 2022/11/3 19:59
 */

public class Largest1BorderedSquare {

    public static void main(String[] args) {
        int[][] nums = {{1,1,1},{1,0,1},{1,1,1}};
        System.out.println(new Largest1BorderedSquare().largest1BorderedSquare(nums));
    }

    public int largest1BorderedSquare1(int[][] grid) {
        TreeMap<Integer, HashSet<Pair<Integer, Integer>>> map1 = new TreeMap<>();
        HashMap<Integer, HashSet<Pair<Integer, Integer>>> map2 = new HashMap<>();
        boolean flag = false;
        int m = grid.length, n = grid[0].length;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    flag = true;
                    int temp = 1;
                    while (i + temp < m && j + temp < n && grid[i + temp][j] == 1 && grid[i][j + temp] == 1) {
                        if (!map1.containsKey(temp)) map1.put(temp, new HashSet<>());
                        map1.get(temp).add(new Pair<>(i, j));
                        ++temp;
                    }
                }
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    int temp = 1;
                    while (i - temp >= 0 && j - temp >= 0 && grid[i - temp][j] == 1 && grid[i][j - temp] == 1) {
                        if (!map2.containsKey(temp)) map2.put(temp, new HashSet<>());
                        map2.get(temp).add(new Pair<>(i, j));
                        ++temp;
                    }
                }
            }
        }
        while (!map1.isEmpty()) {
            Map.Entry<Integer, HashSet<Pair<Integer, Integer>>> entry = map1.pollLastEntry();
            for (Pair<Integer, Integer> pair : entry.getValue()) {
                Integer key = entry.getKey();
                int x = pair.getKey() + key;
                int y = pair.getValue() + key;
                if (map2.containsKey(key) && map2.get(key).contains(new Pair<>(x, y))) return (key + 1) * (key + 1);
            }
        }
        return flag ? 1 : 0;
    }

    public int largest1BorderedSquare(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int[][] row = new int[m][n + 1], col = new int[m + 1][n];
        int ans = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    row[i][j + 1] = row[i][j] + 1;
                    col[i + 1][j] = col[i][j] + 1;
                }
                int min = Math.min(row[i][j + 1], col[i + 1][j]);
                for (int k = min; k > 0; k--) {
                    if (row[i - k + 1][j + 1] >= k && col[i + 1][j - k + 1] >= k) ans = Math.max(ans, k);
                }
            }
        }
        return ans * ans;
    }
}
